///////////////////////////////////////////////////////////////////////////
//
// Spring Engine Source File.
// Copyright (C), Dengtao 2011-2021
// ----------------------------------------------------------------------
// File name:   SfMemoryTracker.h
// Version:     v1.0.0
// Created:     2013/06/14 17:45 by dengtao
// Compilers:   Visual Studio 2008
// Description: 
// ----------------------------------------------------------------------
// History:
//
///////////////////////////////////////////////////////////////////////////

#ifndef _SfMemoryTracker_H_
#define _SfMemoryTracker_H_

#include "SfBaseDefines.h"
#include "SfDelegate.h"
#include "SfFixedString.h"
#include <map>
#include <list>

namespace Sunflower
{
//////////////////////////////////////////////////////////////////////////
//Summary:
//	Memory tracker
//////////////////////////////////////////////////////////////////////////
class MemoryTracker
{
public:
	// 
	// struct for alloc info
	struct MemoryAllocInfo
	{
		void* Addr;
		size_t RequestSize;
		FixedString FileName;
		int LineNum;
		FixedString FuncName;

		MemoryAllocInfo(void* addr, size_t size, 
			const char* file, int line, const char* func)
			: Addr(addr)
			, RequestSize(size)
			, FileName(file)
			, LineNum(line)
			, FuncName(func)
		{
		}

		MemoryAllocInfo(const MemoryAllocInfo& other)
		{
			Copy(*this, other);
		}

		MemoryAllocInfo& operator =(MemoryAllocInfo& other)
		{
			Copy(*this, other);
			return *this;
		}

		static void Copy(MemoryAllocInfo& dest, const MemoryAllocInfo& src)
		{
			dest.Addr = src.Addr;
			dest.RequestSize = src.RequestSize;
			dest.FileName = src.FileName;
			dest.LineNum = src.LineNum;
			dest.FuncName = src.FuncName;
		}

		static void Make(MemoryAllocInfo& mai, void* addr, size_t size, 
			const char* file, int line, const char* func)
		{
			mai.Addr = addr;
			mai.RequestSize = size;
			mai.FileName = file;
			mai.LineNum = line;
			mai.FuncName = func;
		}
	};

public:
	//
	//Summary:
	//	constructor.
	MemoryTracker();

	//
	//Summary:
	//	destructor.
	virtual ~MemoryTracker();

	//
	//Summary:
	//  Process Memory allocate.
	virtual void ProcMemoryAlloc(void* p, size_t size, 
		const char* fileName, int line, const char* funcName);

	//
	//Summary:
	//	Process memory freed.
	virtual void ProcMemoryFree(void* p);

	//
	//Summary:
	//	Reset
	virtual void Reset();

	//
	//Summary:
	//	interface to debug
	int GetUsingCount() const { return (int)m_UsingMais.size(); }
	int GetFreeCount() const  { return (int)m_FreeMais.size(); }

protected:
	//
	//Summary:
	//	call-back on memory allocated.
	virtual void OnMemoryAlloc(MemoryAllocInfo* mai);

	//
	//Summary:
	//	call-back on memory freed.
	virtual void OnMemoryFree(MemoryAllocInfo* mai);

	//
	//Summary:
	//	alloc a MemoryAllocInfo object.
	virtual MemoryAllocInfo* CreateMai(void* p, size_t size, 
		const char* fileName, int line, const char* funcName);

	//
	//Summary:
	//	Free a mai object.
	virtual void ReleaseMai(MemoryAllocInfo* mai);

	//
	//Summary:
	//	Remove free Mais;
	virtual void RemoveFreeMais();

	//
	//Summary:
	//	Remove using mais.
	virtual void RemoveUsingMais();

protected:
	typedef std::map<void*, MemoryAllocInfo*> MaiMap;
	typedef MaiMap::iterator MaiMapIterator;
	typedef MaiMap::const_iterator MaiMapConstIterator;
	typedef std::list<MemoryAllocInfo*> MaiList;
	typedef MaiList::iterator MaiListIterator;
	typedef MaiList::const_iterator MaiListConstIterator;

	// using items.
	MaiMap m_UsingMais;	

	// free items for mai pool
	MaiList m_FreeMais;
}; // end of class MemoryTracker

} // end of namespace Sunflower

#endif